# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

# pyre-strict

import math
import re
import string
from typing import Dict

from ..base_test_generator import BaseTestGenerator


class BaseConstraintSatisfactionTestGenerator(BaseTestGenerator):
    """
    DOC_STRING
    """

    def __init__(self) -> None:
        """
        Initialize constraints
        """
        self.length = 0
        self.prime = False
        self.has_digit = False
        self.has_uppercase = False
        self.has_lowercase = False
        self.has_digit = False
        self.has_special = False
        self.has_vowel = False
        self.has_consonant = False
        self.has_whitespace = False
        self.unique_chars = 0
        self.is_palindrome = False
        self.has_alphabet = False
        self.case_ratio = 0.0
        self.numeric_sequence = False
        self.most_common_char = ""
        self.least_common_char = ""
        self.vowel_count = 0
        self.consonant_count = 0
        self.digit_count = 0
        self.first_three_chars = ""
        self.total_tests = 0
        self.uppercase_count = 0
        self.lowercase_count = 0
        self.unique_characters = 0
        self.special_count = 0

    def func_name(self) -> str:
        return "Constraint Satisfaction Generator"

    def calculate_constraints(self, random_seed: str) -> None:
        def is_prime(n: int) -> bool:
            if n <= 1 or (n % 2 == 0 and n > 2):
                return False
            return all(n % i for i in range(3, int(math.sqrt(n)) + 1, 2))

        def is_fibonacci(n: int) -> bool:
            x = 5 * n**2
            return math.isqrt(x + 4) ** 2 == x + 4 or math.isqrt(x - 4) ** 2 == x - 4

        vowels = "aeiouAEIOU"
        consonants = "bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ"
        self.length = len(random_seed)
        self.prime = is_prime(self.length)
        self.has_uppercase = any(c.isupper() for c in random_seed)
        self.has_lowercase = any(c.islower() for c in random_seed)
        self.has_digit = any(c.isdigit() for c in random_seed)
        self.has_special = any(c in string.punctuation for c in random_seed)
        self.has_vowel = any(c in vowels for c in random_seed)
        self.has_consonant = any(c in consonants for c in random_seed)
        self.has_whitespace = " " in random_seed
        self.unique_chars = len(set(random_seed))
        self.is_palindrome = random_seed == random_seed[::-1]
        self.has_alphabet = any(c.isalpha() for c in random_seed)
        self.uppercase_count = sum(1 for char in random_seed if char.isupper())
        self.lowercase_count = sum(1 for char in random_seed if char.islower())
        self.case_ratio = (
            self.uppercase_count / self.lowercase_count
            if self.lowercase_count != 0
            else -1
        )
        self.numeric_sequence = re.search(r"\d+", random_seed) is not None
        self.vowel_count = sum(1 for char in random_seed if char.lower() in vowels)
        self.consonant_count = sum(
            1 for char in random_seed if char.lower() in consonants
        )
        self.digit_count = sum(char.isdigit() for char in random_seed)
        self.special_count = sum(c in string.punctuation for c in random_seed)

        self.total_tests = 20

    def generate_test_case(self) -> tuple[str, bytes, str]:
        """
        Generate a test case based on constraints
        """
        return NotImplemented

    def generate_prompt(self, code: str) -> str:
        """
        Generate a prompt based on the test case based on constraints
        """
        return NotImplemented

    def compile_and_run(self, code: str, input: bytes) -> str:
        """
        Compile and run the test case
        """
        return NotImplemented

    def score_from_output(self, output: str) -> float:
        """
        Score the output
        """
        return NotImplemented

    def generate_test_case_as_dict(self) -> Dict[str, str]:
        """
        Generate a test case based and return in dict
        """
        (language, answer, test_case) = self.generate_test_case()
        return {
            "mutated_prompt": self.generate_prompt(test_case),
            "challenge_type": "constraint_satisfaction",
            "language": language,
            "code": test_case,
            "answer": repr(answer),
        }
